﻿using SmartPlant.OdDrawingsLib;
using SmartPlant.OdDrawingsLib.ExDbLayout;
using SmartPlant.OdDrawingsLib.Export.Pdf;
using SmartPlant.OdKernelLib.Export.Pdf;
using SmartPlant.WinCore.Helper;
using Teigha.Core;
using Teigha.TD;

namespace SmartPlant.CADView
{
    /// <summary>
    /// CADViewControl.xaml 的交互逻辑
    /// </summary>
    public partial class CADViewControl : System.Windows.Controls.UserControl, IDisposable
    {
        private OdDbDatabase m_CurrentDatabase;
        private OdExCustomServices m_HostAppServices;
        private OdExSystemServices m_SystemServices;

        public CADViewControl()
        {
            m_SystemServices = new OdExSystemServices();
            m_HostAppServices = new OdExCustomServices();
            InitializeComponent();
        }

        protected override void OnInitialized(EventArgs e)
        {
            base.OnInitialized(e);
            InitOdaSdk();
        }

        public void Dispose()
        {
            if (m_dwgControl.IsRenderingInitialized())
                m_dwgControl.UnInit();

            UnInitOdaSdk();
        }

        #region Initialize/Uninitialize ODA SDK
        private void InitOdaSdk()
        {
            StartRootTransaction();

            TD_Db.odInitialize(m_SystemServices);

            LoadModules();
        }

        private void LoadModules()
        {
            Teigha.Core.Globals.odrxDynamicLinker().loadModule("GripPoints");
        }

        private void UnInitOdaSdk()
        {
            StopRootTransaction();

            try
            {
                TD_Db.odUninitialize();
            }
            catch (OdError err)
            {
                LoggerHelper.Current.Error(err.Message, err);
                Console.WriteLine("Cleanup error: " + err.description());
            }
            finally
            {
                Teigha.Core.Helpers.odUninit();
            }
        }
        #endregion

        #region Root Application Memory Transaction
        private MemoryTransaction rootTransaction;
        private void StartRootTransaction()
        {
            if (rootTransaction != null)
                return;
            rootTransaction = MemoryManager.GetMemoryManager().StartTransaction();
        }

        private void StopRootTransaction()
        {
            if (rootTransaction == null)
                return;
            MemoryManager.GetMemoryManager().StopTransaction(rootTransaction);
            rootTransaction = null;
        }
        #endregion

        #region Current OdDbDatabase Memory Transaction
        private MemoryTransaction mTrCurrentDatabase = null;

        private void StartTransactionForCurrentDatabase()
        {
            if (mTrCurrentDatabase != null)
                StopTransactionForCurrentDatabase();
            mTrCurrentDatabase = MemoryManager.GetMemoryManager().StartTransaction();
        }

        private void StopTransactionForCurrentDatabase()
        {
            if (mTrCurrentDatabase == null)
                return;
            MemoryManager.GetMemoryManager().StopTransaction(mTrCurrentDatabase);
            mTrCurrentDatabase = null;
        }
        #endregion

        #region Helpers
        private void ResetPanRotation()
        {
            m_dwgControl.EnableRotation(false);
            m_dwgControl.EnablePan(false);
        }

        private string OnFormDwgFileOpen()
        {
            Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();

            dlg.DefaultExt = ".dwg";
            dlg.Filter = "DWG files (.dwg)|*.dwg";

            if (dlg.ShowDialog() != true)
                return String.Empty;
            return dlg.FileName;
        }

        private void AppendEntityToDatabase(OdDbEntity ent)
        {
            if (ent == null || m_CurrentDatabase == null)
                return;
            OdDbDatabase db = m_CurrentDatabase;

            if (m_dwgControl.IsRenderingInitialized())
                m_dwgControl.OnPrePaintUpdate();

            OdDbObjectId spaceId = OdExAuxUtilities.activeBlockTableRecord(db);
            OdDbBlockTableRecord pSpace = spaceId.safeOpenObject(OpenMode.kForWrite) as OdDbBlockTableRecord;
            pSpace.appendOdDbEntity(ent);

            if (m_dwgControl.IsRenderingInitialized())
                m_dwgControl.OnPostPaintUpdate();
        }
        #endregion

        #region Functionality
        private void OnOpenAndRenderDwgFile()
        {
            string dwgFilePath = OnFormDwgFileOpen();
            if (string.IsNullOrEmpty(dwgFilePath))
                return;
            OnOpenAndRenderDwgFile(dwgFilePath);
        }

        public void OnOpenAndRenderDwgFile(string dwgFilePath)
        {
            bool enableFuntionality = true;
            try
            {
                if (m_dwgControl.IsRenderingInitialized())
                    m_dwgControl.OnReleaseImageSurface();
                StartTransactionForCurrentDatabase();

                if (!string.IsNullOrEmpty(dwgFilePath))
                {
                    m_CurrentDatabase = m_HostAppServices.readFile(dwgFilePath);

                    if (m_dwgControl.IsRenderingInitialized())
                        m_dwgControl.UnInit();

                    m_dwgControl.Init(m_CurrentDatabase);
                }
            }
            catch (Exception err)
            {
                LoggerHelper.Current.Error(err.Message, err);
                enableFuntionality = false;
                StopTransactionForCurrentDatabase();
            }

            OnZoom(enableFuntionality);
            OnMouseEditor(enableFuntionality);
        }

        private void OnZoomToExtents()
        {
            if (!m_dwgControl.IsInitialized)
                return;

            m_dwgControl.ZoomToExtents();
        }

        private void OnZoom(bool isEnable)
        {
            m_dwgControl.EnableZoom(isEnable);
        }

        private void OnPan(bool isEnable)
        {
            if (isEnable)
            {
                m_dwgControl.EnableRotation(false);
            }

            m_dwgControl.EnableMouseEditor(!isEnable);
            m_dwgControl.EnablePan(isEnable);
        }

        private void OnRotation(bool isEnable)
        {
            if (isEnable)
            {
                m_dwgControl.EnablePan(false);
            }

            m_dwgControl.EnableMouseEditor(!isEnable);
            m_dwgControl.EnableRotation(isEnable);
        }

        private void OnMouseEditor(bool isEnable)
        {
            m_dwgControl.EnableMouseEditor(isEnable);
        }

        private void OnExportPDF2d()
        {
            if (m_CurrentDatabase == null)
                return;

            Microsoft.Win32.SaveFileDialog savePdf = new Microsoft.Win32.SaveFileDialog();
            savePdf.DefaultExt = ".pdf";
            savePdf.Title = "导出 PDF 文件";
            savePdf.Filter = "PDF 文件|*.pdf";

            if (savePdf.ShowDialog() != true)
                return;

            MemoryTransaction mTr = MemoryManager.GetMemoryManager().StartTransaction();

            OdExPdfExportParamsFiller paramsFiller = OdExDwgToPdfExportParamsFiller.CreateDefault();

            paramsFiller.PdfFilePath = savePdf.FileName;

            OdStringArray layouts = new OdStringArray();
            OdDbLayoutExamples.FillLayoutList(m_CurrentDatabase, layouts, paramsFiller.AllLayouts, false);
            paramsFiller.LayoutList = layouts;

            try
            {
                using (PDFExportParams parametrsExport = paramsFiller.Generate(m_CurrentDatabase, m_HostAppServices))
                {
                    OdExPdfExport exportExample = new OdExPdfExport();
                    exportExample.Export(parametrsExport);
                }
            }
            catch (Exception err)
            {
                LoggerHelper.Current.Error(err.Message, err);
                System.Windows.MessageBox.Show(
                err.Message,
                "Information");
            }
            finally
            {
                MemoryManager.GetMemoryManager().StopTransaction(mTr);
            }
        }
        #endregion

        #region Event
        private void OnOpenDwg(object sender, System.Windows.RoutedEventArgs e)
        {
            OnOpenAndRenderDwgFile();
            OnPan(true);
        }

        private void OnExportPDF(object sender, System.Windows.RoutedEventArgs e)
        {
            OnExportPDF2d();
            OnPan(true);
        }

        private void OnZoomMax(object sender, System.Windows.RoutedEventArgs e)
        {
            OnZoomToExtents();
            OnPan(true);
        }

        private void OnPan(object sender, System.Windows.RoutedEventArgs e)
        {
            OnPan(true);
        }
        #endregion
    }
}
